/*
 * Copyright (c) 2025 CAX Conversion Project
 */
package com.comac.ins.cax.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.cax.domain.CaxConvertInfo;
import com.comac.ins.cax.domain.CaxFileInfo;
import com.comac.ins.cax.domain.bo.CaxFileInfoBo;
import com.comac.ins.cax.domain.vo.CaxFileInfoExportVo;
import com.comac.ins.cax.domain.vo.CaxFileInfoVo;
import com.comac.ins.cax.mapper.CaxFileInfoMapper;
import com.comac.ins.cax.service.ICaxFileInfoService;
import com.comac.ins.cax.utils.FileUtils;
import com.comac.ins.common.core.domain.model.LoginUser;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.DateUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.excel.utils.ExcelUtil;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.common.satoken.utils.LoginHelper;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author yk
 * @desc CAX转换文件service
 * @date 2024-06-19 11:00
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CaxFileInfoServiceImpl implements ICaxFileInfoService {

    @Autowired
    private CaxFileInfoMapper caxFileInfoMapper;

    private static final String UPLOAD_PATH = "/data/file/source/";

    @Override
    public CaxFileInfo uploadFile(MultipartFile file, String type) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        Long userId = loginUser.getUserId();
        Long deptId = loginUser.getDeptId();
        if (file == null || "".equals(file.getOriginalFilename())) {
            return null;
        }
        try {
            String fileName = file.getOriginalFilename();
            Assert.notNull(fileName, "fileName字段非法");
            String fileExt = FileUtils.getFileExt(fileName);
            long size = file.getSize();
            String filePath = createFilePath();
            // 将文件保存到服务器
            Path destinationFile = Paths.get(filePath, fileName);
            Files.copy(file.getInputStream(), destinationFile);
            // 保存DB文件记录
            CaxFileInfo caxFileInfo = new CaxFileInfo();
            caxFileInfo.setType(type);
            caxFileInfo.setName(fileName);
            caxFileInfo.setPath(filePath + fileName);
            caxFileInfo.setExtension(fileExt);
            caxFileInfo.setSize(String.valueOf(size));
            caxFileInfo.setCreateBy(userId);
            caxFileInfo.setUpdateBy(userId);
            caxFileInfo.setCreateDept(deptId);
            caxFileInfoMapper.insert(caxFileInfo);
            return caxFileInfo;
        } catch (IOException e) {
            log.error("文件上传失败！", e);
            throw new BaseException("文件上传失败！");
        }
    }

    @Override
    public void download(HttpServletResponse response, Long id) {
        CaxFileInfoVo caxFileInfoVo = caxFileInfoMapper.selectVoById(id);
        if (Objects.isNull(caxFileInfoVo)) {
            throw new BaseException("未查询到源文件信息");
        }
        try {
            FileUtils.downloadFile(response, caxFileInfoVo.getPath(), caxFileInfoVo.getName());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BaseException("文件下载失败！");
        }
    }

    @Override
    public void export(HttpServletResponse response, CaxFileInfoBo bo) {
        bo.setEndCreateTime(DateUtils.toOneDayEndTime(bo.getEndCreateTime()));
        //查询需要导出的数据
        List<CaxFileInfoVo> caxFileInfoVoList = caxFileInfoMapper.selectVoExportList(bo);

        if (CollectionUtils.isEmpty(caxFileInfoVoList)) {
            throw new BaseException("没有需要导出的数据！");
        }

        //转换数据
        List<CaxFileInfoExportVo> exportVoList = new ArrayList<>();
        for (CaxFileInfoVo caxFileInfoVo : caxFileInfoVoList) {
            CaxFileInfoExportVo exportVo = new CaxFileInfoExportVo();
            BeanUtils.copyProperties(caxFileInfoVo, exportVo);
            exportVoList.add(exportVo);
        }

        // 封装导出的data
        Map<String, Object> data = new HashMap<>();
        String fileName = "源文件信息";
        data.put(fileName, exportVoList);
        ExcelUtil.exportWithOutTemplateMultiList(data, fileName, CaxFileInfoExportVo.class, response);
    }

    @Override
    @Transactional
    public List<CaxFileInfo> batchUploadFile(MultipartFile[] files, String type) {
        List<CaxFileInfo> list = new ArrayList<>();
        for (MultipartFile file : files) {
            CaxFileInfo caxFileInfo = this.uploadFile(file, type);
            list.add(caxFileInfo);
        }
        return list;
    }

    /**
     * 创建文件上传路径
     *
     * @return 文件上传路径
     * @throws IOException 异常
     */
    public String createFilePath() throws IOException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String currentDate = sdf.format(new Date());
        String filePath = UPLOAD_PATH + currentDate + "/" + IdUtil.simpleUUID() + "/";
        // 创建目标目录如果它不存在
        Files.createDirectories(Paths.get(filePath));
        return filePath;
    }

    @Override
    public CaxFileInfo queryById(Long id) {
        return caxFileInfoMapper.selectById(id);
    }

    @Override
    public TableDataInfo<CaxFileInfoVo> queryPageList(CaxFileInfoBo bo) {
        bo.setEndCreateTime(DateUtils.toOneDayEndTime(bo.getEndCreateTime()));
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(bo.getPageNum());
        pageQuery.setPageSize(bo.getPageSize());
        LambdaQueryWrapper<CaxFileInfo> lqw = buildQueryWrapper(bo);
        Page<CaxFileInfoVo> result = caxFileInfoMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public Boolean deleteBatchIds(List<Long> ids) {
        return caxFileInfoMapper.deleteBatchIds(ids) > 0;
    }

    private LambdaQueryWrapper<CaxFileInfo> buildQueryWrapper(CaxFileInfoBo bo) {
        LambdaQueryWrapper<CaxFileInfo> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getType()), CaxFileInfo::getType, bo.getType());
        lqw.eq(StringUtils.isNotBlank(bo.getExtension()), CaxFileInfo::getExtension, bo.getExtension());
        lqw.like(StringUtils.isNotBlank(bo.getName()), CaxFileInfo::getName, bo.getName());
        lqw.between(ObjectUtils.isNotEmpty(bo.getBeginCreateTime()) && ObjectUtils.isNotEmpty(bo.getEndCreateTime()),
                CaxFileInfo::getCreateTime, bo.getBeginCreateTime(), bo.getEndCreateTime());
        lqw.orderByDesc(CaxFileInfo::getCreateTime);
        return lqw;
    }
}
